//
//  CCPNetworking.m
//  CCPNetworkingDemo
//
//  Created by CCP on 16/5/12.
//  Copyright © 2016年 CCP. All rights reserved.
//

#import "CCPNetworking.h"
#import "AFNetworking.h"
#import "AFNetworkActivityIndicatorManager.h"
#import "MBProgressHUD.h"
#import "MBProgressHUD+ADD.h"
#import "AppDelegate.h"

#ifdef DEBUG
#   define CCPLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define CCPLog(...)
#endif

static NSMutableArray *tasks;
static BOOL overdueToken;//过期token(解决有多个接口同时请求时token报错问题)

@implementation CCPNetworking

+ (CCPNetworking *)sharedCCPNetworking
{
    static CCPNetworking *handler = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        handler = [[CCPNetworking alloc] init];
    });
    return handler;
}

+(NSMutableArray *)tasks{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        tasks = [[NSMutableArray alloc] init];
    });
    return tasks;
}

+ (NSInteger)showErrorType:(NSError *)error {
    NSData *data = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
    NSDictionary *body = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    if (!body) {
        return 0;
    }
    return [(NSNumber *)body[@"error"] integerValue];
}
/* 输出http响应的状态码 */
+ (NSInteger)showResponseCode:(NSURLSessionDataTask *)task {
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)task.response;
    NSInteger responseStatusCode = [httpResponse statusCode];
    return responseStatusCode;
}

+(CCPURLSessionTask *)requestWithType:(httpMethod)type isJson:(BOOL)isJson WithUrl:(NSString *)url params:(id)params loadingImageArr:(NSMutableArray *)loadingImageArr  toShowView:(UIView *)showView cache:(BOOL)cache retryNum:(int)retryNum success:(CCPResponseSuccess)success fail:(CCPResponseFail)fail showHUD:(BOOL)showHUD{
    
    if (url==nil) {
        return nil;
    }
    
    NSLog(@"requestURL:%@",url);
    
    if (showHUD == YES) {
//        [MBProgressHUD dissmissShowView:showView];
    }
    
    AFHTTPSessionManager *manager=[self getAFManager];
//    manager.requestSerializer = isJson?[AFJSONRequestSerializer serializer]:[AFHTTPRequestSerializer serializer];
    //    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    
    //    [manager.requestSerializer setValue:VALID_STRING(TOKEN) forHTTPHeaderField:@"token"];
//    [params setObject:VALID_STRING(TOKEN) forKey:@"token"];
//    if (![[params allKeys] containsObject:@"uid"]) {
//        [params setObject:VALID_STRING(UID) forKey:@"uid"];
//    }
    
    url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    CCPURLSessionTask *sessionTask=nil;
    //GET
    if (type== GET) {
        [manager GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (showHUD==YES) {
//                [MBProgressHUD dissmissShowView:showView];
            }
//            NSInteger code = 0;
//            if (responseObject[@"code"]) {
//                code = [responseObject[@"code"] integerValue];
//                if (code == 400) {
//                    [MBProgressHUD showInformation:responseObject[@"message"] toView:WINDOW andAfterDelay:HUD_TIME];
//                }else if (code == 300 && !overdueToken){
//                    [self timeOutAction];
//                    return;
//                }
//            }
            if (success) {
                success(responseObject, YES);
            }
            NSLog(@"GET请求成功");
            [[self tasks] removeObject:sessionTask];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"error:%@",error.localizedDescription);
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
//                [MBProgressHUD dissmissShowView:showView];
            }
            NSLog(@"URL:%@",url);
            
            //自动重试
            if (retryNum > 0) {
                [self requestWithType:type isJson:isJson WithUrl:url params:params loadingImageArr:loadingImageArr toShowView:showView cache:cache retryNum:retryNum-1 success:success fail:fail showHUD:showHUD];
            }else{
                if (fail) {
                    fail(error, task);
                }
            }
        }];
        
    }
    //POST
    else if (type == POST){
        sessionTask = [manager POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
//            NSInteger code = 0;
//            if (responseObject[@"code"]) {
//                code = [responseObject[@"code"] integerValue];
//                if (code == 400) {
//                    [MBProgressHUD showInformation:responseObject[@"message"] toView:WINDOW andAfterDelay:HUD_TIME];
//                }else if (code == 300 && !overdueToken){
//                    [self timeOutAction];
//                    return;
//                }
//            }
            
            if (success) {
                success(responseObject, YES);
            }
            
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
//                [MBProgressHUD dissmissShowView:showView];
                
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
                dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
                    
                    sleep(1.0);
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        
//                        [MBProgressHUD dissmissShowView:showView];
                    });
                });
                
            }
            
            //自动重试
            if (retryNum > 0) {
                [self requestWithType:type isJson:isJson WithUrl:url params:params loadingImageArr:loadingImageArr toShowView:showView cache:cache retryNum:retryNum-1 success:success fail:fail showHUD:showHUD];
            }else{
                if (fail) {
                    fail(error, task);
                }
                NSLog(@"error:%@",error.localizedDescription);
                //                if (![self isHaveNetwork] && type != GET) {
                //                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"网络异常，请检查网络连接" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil];
                //                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                //                        [alertView show];
                //                    });
                //                }
            }
            
        }];
    }
    //PUT
    else if (type == PUT){
        sessionTask = [manager PUT:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (success) {
                success(responseObject, YES);
            }
            
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
//                [MBProgressHUD dissmissShowView:showView];
                
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //            NSHTTPURLResponse *response = (NSHTTPURLResponse*)task.response;
            //            //通讯协议状态码
            //            NSInteger statusCode = response.statusCode;
            //            //服务器返回的业务逻辑报文信息
            //            NSString* errResponse = [[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding];
            //            NSData *jsonData = [errResponse dataUsingEncoding:NSUTF8StringEncoding];
            //            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
            //                                                                options:NSJSONReadingMutableContainers
            //                                                                  error:nil];
            //            NSLog(@"%@",dic);
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
                dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
                    
                    sleep(1.0);
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        
//                        [MBProgressHUD dissmissShowView:showView];
                    });
                });
                
            }
            //自动重试
            if (retryNum > 0) {
                [self requestWithType:type isJson:isJson WithUrl:url params:params loadingImageArr:loadingImageArr toShowView:showView cache:cache retryNum:retryNum-1 success:success fail:fail showHUD:showHUD];
            }else{
                if (fail) {
                    fail(error, task);
                }
                NSLog(@"error:%@",error.localizedDescription);
                //                if (![self isHaveNetwork] && type != GET) {
                //                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"网络异常，请检查网络连接" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil];
                //                    [alertView show];
                //                }
            }
            
        }];
    }
    //DELTE
    else {
        manager.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:@[@""]];
        sessionTask = [manager DELETE:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (success) {
                success(responseObject, YES);
            }
            
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
//                [MBProgressHUD dissmissShowView:showView];
                
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            [[self tasks] removeObject:sessionTask];
            
            if (showHUD==YES) {
                
                dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
                    
                    sleep(1.0);
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        
//                        [MBProgressHUD dissmissShowView:showView];
                    });
                });
                
            }
            //自动重试
            if (retryNum > 0) {
                [self requestWithType:type isJson:isJson WithUrl:url params:params loadingImageArr:loadingImageArr toShowView:showView cache:cache retryNum:retryNum-1 success:success fail:fail showHUD:showHUD];
            }else{
                if (fail) {
                    fail(error, task);
                }
                NSLog(@"error:%@",error.localizedDescription);
                //                if (![self isHaveNetwork] && type != GET) {
                //                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"网络异常，请检查网络连接" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil];
                //                    [alertView show];
                //                }
            }
        }];
    }
    
    if (sessionTask) {
        [[self tasks] addObject:sessionTask];
    }
    
    return sessionTask;
    
}


+ (CCPURLSessionTask *)uploadWithImages:(NSArray *)imageArr url:(NSString *)url filename:(NSString *)filename names:(NSArray *)nameArr params:(NSDictionary *)params loadingImageArr:(NSMutableArray *)loadingImageArr toShowView:(UIView *)showView progress:(CCPUploadProgress)progress success:(CCPResponseSuccess)success fail:(CCPResponseFail)fail showHUD:(BOOL)showHUD {
    
    
    if (url==nil) {
        return nil;
    }
    
    if (showHUD==YES) {
        
//        [MBProgressHUD showHUDWithImageArr:loadingImageArr andShowView:showView];
    }
    
    //检查地址中是否有中文
    NSString *urlStr=[NSURL URLWithString:url]?url:[self strUTF8Encoding:url];
    
    AFHTTPSessionManager *manager=[self getAFManager];
    
    CCPURLSessionTask *sessionTask = [manager POST:urlStr parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        for (int i = 0; i < imageArr.count; i ++) {
            
            @autoreleasepool{
                
                NSString *imageFileName = filename;
                if (filename == nil || ![filename isKindOfClass:[NSString class]] || filename.length == 0) {
                    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
                    formatter.dateFormat = @"yyyyMMddHHmmss";
                    NSString *str = [formatter stringFromDate:[NSDate date]];
                    imageFileName = [NSString stringWithFormat:@"%@.png", str];
                }
                
                NSString *nameString = (NSString *)nameArr[i];
                
                if ([imageArr[i] isKindOfClass:[UIImage class]]) {
                    UIImage *image = (UIImage *)imageArr[i];
                    
                    NSData *imageData = UIImageJPEGRepresentation(image,0.6);
                    [formData appendPartWithFileData:imageData name:nameString fileName:imageFileName mimeType:@"image/jpg"];
                }else{
                    [formData appendPartWithFileURL:[NSURL fileURLWithPath:imageArr[i]] name:nameString fileName:imageFileName mimeType:@"image/jpg" error:nil];
                }
            }
            
        }
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        CCPLog(@"上传进度--%lld,总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
        
        if (progress) {
            
            progress(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
            
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (success) {
            success(responseObject, YES);
        }
        
        [[self tasks] removeObject:sessionTask];
        
        if (showHUD==YES) {
            
//            [MBProgressHUD dissmissShowView:showView];
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (fail) {
            fail(error, task);
        }
        
        [[self tasks] removeObject:sessionTask];
        
        if (showHUD==YES) {
            
//            [MBProgressHUD dissmissShowView:showView];
        }
        
    }];
    
    if (sessionTask) {
        [[self tasks] addObject:sessionTask];
    }
    
    return sessionTask;
    
}


+ (CCPURLSessionTask *)downloadWithUrl:(NSString *)url saveToPath:(NSString *)saveToPath loadingImageArr:(NSMutableArray *)loadingImageArr progress:(CCPDownloadProgress )progressBlock toShowView:(UIView *)showView success:(CCPResponseSuccess )success failure:(CCPResponseFail )fail showHUD:(BOOL)showHUD{
    
    if (url==nil) {
        return nil;
    }
    
    if (showHUD==YES) {
        
//        [MBProgressHUD showHUDWithImageArr:loadingImageArr andShowView:showView];
        
    }
    
    NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    AFHTTPSessionManager *manager = [self getAFManager];
    
    CCPURLSessionTask *sessionTask = nil;
    
    sessionTask = [manager downloadTaskWithRequest:downloadRequest progress:^(NSProgress * _Nonnull downloadProgress) {
        
        CCPLog(@"下载进度--%.1f",1.0 * downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
        
        //回到主线程刷新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressBlock) {
                
                progressBlock(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
            }
        });
        
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        if (!saveToPath) {
            NSURL *downloadURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
            CCPLog(@"默认路径--%@",downloadURL);
            return [downloadURL URLByAppendingPathComponent:[response suggestedFilename]];
            
        }else{
            NSURL *downloadURL = [NSURL fileURLWithPath:saveToPath];
            CCPLog(@"目标下载路径--%@",downloadURL);
            return [downloadURL URLByAppendingPathComponent:[response suggestedFilename]];
        }
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        
        [[self tasks] removeObject:sessionTask];
        
        if (error == nil) {
            
            if (success) {
                success([filePath path], YES);//返回完整路径
            }
            
        } else {
            
            if (fail) {
                
                fail(error, nil);
                
            }
        }
        
        if (showHUD==YES) {
            
//            [MBProgressHUD dissmissShowView:showView];
        }
        
    }];
    
    //开始下载
    [sessionTask resume];
    //
    if (sessionTask) {
        
        [[self tasks] addObject:sessionTask];
        
    }
    
    return sessionTask;
    
}



+ (AFHTTPSessionManager *)getAFManager{
    
    static AFHTTPSessionManager *httpManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
        httpManager = [AFHTTPSessionManager manager];
        httpManager.responseSerializer = [AFJSONResponseSerializer serializer];//设置返回数据为json
        httpManager.requestSerializer = [AFJSONRequestSerializer serializer];// 请求
        //        httpManager.responseSerializer = [AFHTTPResponseSerializer serializer];//设置返回NSData 数据
        httpManager.requestSerializer.stringEncoding = NSUTF8StringEncoding;
        httpManager.requestSerializer.timeoutInterval= 20;
        httpManager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",
                                                                                      @"text/html",
                                                                                      @"text/json",
                                                                                      @"text/plain",
                                                                                      @"text/javascript",
                                                                                      @"text/xml",
                                                                                      @"image/*"]];
    });
    
    return httpManager;
}

#pragma makr - 开始监听程序在运行中的网络连接变化
+ (void)startMonitoring
{
    // 1.获得网络监控的管理者
    AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
    // 2.设置网络状态改变后的处理
    [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        // 当网络状态改变了, 就会调用这个block
        switch (status)
        {
            case AFNetworkReachabilityStatusUnknown: // 未知网络
                
                [CCPNetworking sharedCCPNetworking].networkStats=StatusUnknown;
                
                break;
                
            case AFNetworkReachabilityStatusNotReachable: // 没有网络(断网)
                
                [CCPNetworking sharedCCPNetworking].networkStats=StatusNotReachable;
                
                break;
                
            case AFNetworkReachabilityStatusReachableViaWWAN: // 手机自带网络
                
                [CCPNetworking sharedCCPNetworking].networkStats=StatusReachableViaWWAN;
                
                break;
                
            case AFNetworkReachabilityStatusReachableViaWiFi: // WIFI
                
                [CCPNetworking sharedCCPNetworking].networkStats=StatusReachableViaWiFi;
                
                break;
        }
    }];
    
    [mgr startMonitoring];
}

+ (NetworkStatu)checkNetStatus {
    
    [self startMonitoring];
    
    if ([CCPNetworking sharedCCPNetworking].networkStats == StatusReachableViaWiFi) {
        
        return StatusReachableViaWiFi;
        
    } else if ([CCPNetworking sharedCCPNetworking].networkStats == StatusNotReachable) {
        
        return StatusNotReachable;
        
    } else if ([CCPNetworking sharedCCPNetworking].networkStats == StatusReachableViaWWAN) {
        
        return StatusReachableViaWWAN;
        
    } else {
        
        return StatusUnknown;
        
    }
    
}


//+ (BOOL) isHaveNetwork {

//    Reachability *conn = [Reachability reachabilityForInternetConnection];
//    
//    if ([conn currentReachabilityStatus] == NotReachable) {
//        
//        return NO;
//        
//    } else {
//        
//        return YES;
//    }
//}


+ (NSString *)strUTF8Encoding:(NSString *)str{
    
    return [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}

#pragma mark token失效处理
+(void)timeOutAction{
//    NSLog(@"token失效");
//     //清理用户信息
//    [[SLParamManager shareInstance] cleanUserInfo];
//    [[NSUserDefaults standardUserDefaults] synchronize];
////    [MBProgressHUD showInformation:@"" toView:WINDOW andAfterDelay:1.0];
//    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        overdueToken = NO;
//        [delegate showLoginView:NO];
//    });
//    overdueToken = YES;
}

- (void)dealloc
{
    NSLog(@"================================%s====================================", __FUNCTION__);
    [[AFNetworkReachabilityManager sharedManager] stopMonitoring];
}
@end


